#include "mainui.h"
#include "ui_mainui.h"
#include <QCryptographicHash>
#include <QApplication>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QPixmap>
#include <QPalette>
#include <QBitmap>
#include <QTime>
#include <QtCore/QObject>
#include <QTimer>
#include "aes_gcm.h"
extern QString username;//引用mainwindow里面的全局变量，用户名和密码
extern QString password;
extern int usernum;
unsigned char* getkey(int k){//扩展为256位密钥
    unsigned char * r;
    r=new unsigned char[32];
    int i;
    for(i=0;i<32;i++){
        r[i]=(unsigned char)k;
    }
    return r;
}

mainui::mainui(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::mainui)
{
    tcpClient=new QTcpSocket(this);
    //连接信号槽
    QObject::connect(tcpClient, &QTcpSocket::readyRead, this, &mainui::ReadData);
    ui->setupUi(this);
    ui->lineIP->setText("127.0.0.1");
    ui->lineport->setText("5000");
    ui->connect->setText("关闭连接");
//    /*
//     * 设置背景图片
//     */
//     QPixmap bgImages(":/new/prefix1/C:/Users/asus/Desktop/beijing1.jpg");
//     QPalette bgPalette = this->palette();
//     bgPalette.setBrush(QPalette::Background,bgImages);
//     this->setPalette(bgPalette);
//     setMask(bgImages.mask());// set background mask attribute same as background's image
    //设置显示时间
     timer = new QTimer(this);
     connect(timer, SIGNAL(timeout()), this, SLOT(qtimeSlot()));
     timer->start(1000);

    aes_gcm aestest(aestest.getgcmchar(getkey(27209),32));
    aestest.input1="FAE";
    aestest.aes_encrypt();

     msglenthforweb=200;
}

mainui::~mainui()
{
    delete ui;
}

QString mainui::getnewString(QString s){
    int n=100;
    if(s.length()>n){
        qDebug()<<"太长了！";
    }else{
        int c=n-s.length();
        int i;
        s+="-";
        for(i=0;i<c-1;i++){
            s+="1";
        }
    }
}

unsigned char* mainui::getkey(int k){//扩展为256位密钥
    unsigned char * r;
    r=new unsigned char[32];
    int i;
    for(i=0;i<32;i++){
        r[i]=(unsigned char)k;
    }
    return r;
}
void mainui::qtimeSlot()//显示时间
{
    QTime qtimeObj = QTime::currentTime();
    QString strTime = qtimeObj.toString(" hh:mm:ss ");
    QDate qdateObj = QDate::currentDate();
    QString strDate = qdateObj.toString("yyyy-MM-dd");
    strDate+=strTime;
    ui->label->setText(strDate);
}
void mainui::on_pushButton_clicked()//返回登录界面，需要断开当前连接
{
    tcpClient->disconnectFromHost();
    disconnect(dis);
    ui->textEdit->clear();
    ui->textEdit_2->clear();
    sendsignal_1();
    this->hide();
}

void mainui::on_sendmsg_clicked() //发送消息，先发给服务器，服务器再发向所有客户端
{                                 //发送消息的格式：data-用户名-原消息长度-经过处理的密文（只进行了aesgcm加密)
    QString msg=ui->textEdit_2->toPlainText();
    aes_gcm aesg(aesg.getgcmchar(getkey(DH.K),32));
    QString plaintext=msg;
     qDebug()<<"the length of plaintext for AES "<<plaintext.length();
     //先给输入字符串
     QString s=plaintext;
     int n=100;
     int c=n-s.length();
     int i;
     s+="-";
     for(i=0;i<c-1;i++){
         s+="1";
     }
     aesg.input1=s;
     aesg.aes_encrypt();//input1->output1,得到的密文是output1，一个QByteArray数组
     qDebug()<<"AES密文的长度"<<aesg.output1.length();
    QByteArray rslt;
    rslt=aesg.output1;
    QString tmp;
    tmp="data-"+username+"-"+QString::number(msg.length())+"-";
    qDebug()<<"tmp :"<<tmp;
    int length;
    length=tmp.toUtf8().length();//对消息头，要先进行utf-8编码，到对方再utf-8解码，否则不支持中文的用户名
    qDebug()<<"tmp length"<<length;
    rslt=tmp.toUtf8()+rslt;
    qDebug()<<"rslt length"<<rslt.length();
    tcpClient->write(rslt.toBase64());
    qDebug()<<"have send";
}

void mainui::on_connect_clicked() //建立连接
{
    QString msg;
    if(ui->connect->text()=="建立连接"){
    QString address;
    address=ui->lineIP->text();
    int port;
    port=ui->lineport->text().toInt();
    tcpClient->abort();//取消已有连接
    tcpClient->connectToHost(address,port);//连接
    //等待连接成功
    if(!tcpClient->waitForConnected(30000))
    {
       qDebug() << "Connection failed!";
       ui->state->setText("连接失败");
       return;
    }
    //连接成功需要向服务器发送用户名和密码
    qDebug() << "Connect successfully!";
    ui->state->setText("连接成功");
    ui->sendmsg->setEnabled(true);
    msg="request-"+username+"-"+password;//需要操作
    tcpClient->write(msg.toUtf8());
    ui->connect->setText("关闭连接");
    return;
    }
    if(ui->connect->text()=="关闭连接"){//断开连接
    ui->connect->setText("建立连接");
    ui->state->setText("等待连接");
    ui->sendmsg->setEnabled(false);//设置发送按钮无效
    ui->connect->setEnabled(false);//设置不能再建立连接，需要返回登录
    tcpClient->disconnectFromHost();
    return;
    }
}
void mainui::ReadData()//接收消息，将数据读到textedit上，出现问题，行间距逐渐扩大(已解决）,需要判断消息类型，分为列表更新消息和普通消息
{
    qDebug()<<"read data";
    QByteArray readbuf=QByteArray::fromBase64(tcpClient->readAll());
    QString recv=QString::fromUtf8(readbuf);
    QStringList list;
    list=recv.split("-");
    if(list.at(0)=="ok"){//如果是列表消息,更新当前用户人数，更新用户列表，显示到表上 ok-服务器rsa.e-rsa.n-KB-当前用户人数（加上了这个新登录的）-用户名1-用户名2-...
        QString tmp;
        tmp=list.at(4);
        ui->currentusrnum->setText(tmp);
        int i;
        QStringList tablelist;
        for(i=5;i<list.count();i++){
            tablelist.append(list.at(i));
        }
        usernamelist=tablelist;
        ui->tableWidget->clear();
        ui->currentusrnum->setText(tmp);
        QStringList header;
        header<<"当前用户人数";
        ui->tableWidget->setColumnCount(1);
        ui->tableWidget->setRowCount(0);
        ui->tableWidget->setHorizontalHeaderLabels(header);//设置表头内容
        QTableWidgetItem *Item;
        ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
        ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
        ui->tableWidget->horizontalHeader()->setVisible(false); //隐藏行表头
        ui->tableWidget->resizeColumnsToContents();
        ui->tableWidget->resizeRowsToContents();
        for(i=0;i<usernamelist.count();i++){
                    Item=new QTableWidgetItem(usernamelist.at(i));
                    QFont font=Item->font();//获取原有字体设置
                    font.setBold(true);//设置为粗体
                    font.setPointSize(12);//字体大小
                    Item->setTextColor(Qt::blue);//字体颜色
                    Item->setFont(font);//设置字体
                    int RowCont;
                    RowCont=ui->tableWidget->rowCount();
                    ui->tableWidget->insertRow(RowCont);//增加一行
                    ui->tableWidget->setItem(i,0,Item);
        }
        return;
    }else if(list.at(0)=="data"){//如果是普通消息 用户名-原消息长度-经过处理的密文
       qDebug()<<"recv msg";
        QString username;
        int length;
        username=list.at(1);
        QString s;
        s=list.at(2);
        length=s.toInt();
        qDebug()<<"username:"<<username;
        qDebug()<<"length:"<<length;
        int readbuflenth=readbuf.length();

        //aes解密
        QString begin;//计算消息头的长度，AES密文的长度
        begin="data-"+username+"-"+list.at(2)+"-";
        QByteArray b;
        b=begin.toUtf8();
        qDebug()<<"begin:"<<begin;
        qDebug()<<"b length:"<<b.length();
        int beginlength=b.length();
        int aescipherlength;
        aescipherlength=readbuf.length()-b.length();//aes密文长度
        QByteArray aescipherbytearray;
        int i;
        for(i=beginlength;i<beginlength+aescipherlength;i++){
            aescipherbytearray.append(readbuf[i]);
        }
        qDebug()<<"readbuf length"<<readbuflenth;
        qDebug()<<"aescipherlength"<<aescipherbytearray.length();
        aes_gcm aesg(aesg.getgcmchar(getkey(DH.K),32));
        aesg.input2=aescipherbytearray;
        aesg.aes_decrypt();
        QString aesoutput;
        aesoutput=aesg.output2;
        qDebug()<<"aes output"<<aesoutput;



        //解密后的数据提取原文，进行MD5和签名验证
        QString msg;
        msg=aesoutput.mid(0,length);
        qDebug()<<"解密获得原文"<<msg;
         qDebug()<<"complete";
         QString uistring;//要显示的字符串
         uistring=username+":"+msg;
         ui->textEdit->append(uistring);
//         }
    }
}

void mainui::Disconnected()
{
}

void mainui::on_toolButton_clicked()//加密测试
{
    test1=new test;
    test1->show();
}
QByteArray mainui::intTo4ByteArray(int i)//整数数组转化为QByteArray
{
    QByteArray ba;
    ba.resize(4);
    ba[0] = (uchar)(0x000000ff & i);
    ba[1] = (uchar)((0x0000ff00&i)>>8);
    ba[2] = (uchar)((0x00ff0000&i)>>16);
    ba[3] = (uchar)((0xff000000&i)>>24);
    return ba;
}
int mainui::ByteArray4ToInt(const QByteArray &bytes)//QByteArray转化为整数数组
{
    int i = bytes[0] & 0x000000FF;
    i |= ((bytes[1] <<8)&0x0000FF00);
    i |= ((bytes[2] <<16)&0x00FF0000);
    i |= ((bytes[3] <<24)&0xFF000000);
    return i;
}
void mainui::Initialize()//显示界面时的初始化，绑定槽，显示用户人数和用户列表
{
  ui->currentusrnum->setText(QString::number(usernum));
  dis=QObject::connect(tcpClient, &QTcpSocket::readyRead, this, &mainui::ReadData);

  //显示用户列表
  QStringList header;
  header<<"当前用户人数";
  ui->tableWidget->setColumnCount(1);
  ui->tableWidget->setRowCount(0);
  ui->tableWidget->setHorizontalHeaderLabels(header);//设置表头内容
  QTableWidgetItem *Item;
  ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
  ui->tableWidget->horizontalHeader()->setStretchLastSection(true);
  ui->tableWidget->horizontalHeader()->setVisible(false); //隐藏行表头
  ui->tableWidget->resizeColumnsToContents();
  ui->tableWidget->resizeRowsToContents();
  for(int i=0;i<usernamelist.count();i++){
              Item=new QTableWidgetItem(usernamelist.at(i));
              QFont font=Item->font();//获取原有字体设置
              font.setBold(true);//设置为粗体
              font.setPointSize(12);//字体大小
              Item->setTextColor(Qt::blue);//字体颜色
              Item->setFont(font);//设置字体
              int RowCont;
              RowCont=ui->tableWidget->rowCount();
              ui->tableWidget->insertRow(RowCont);//增加一行
              ui->tableWidget->setItem(i,0,Item);
  }
}

void mainui::on_cleartextedit_clicked()
{
    ui->textEdit->clear();
}
void mainui::on_sendfalsemsg_clicked(){

}

/*

void mainui::on_sendfalsemsg_clicked()//发送伪造消息进行验证，发送消息helo,但是这个消息的hash值是hel的hash值
{
    QString msg="helo";
    QString msg2="hel";
    //需要一系列的处理
    qDebug()<<"rsa:"<<rsa_a.e;
    qDebug()<<rsa_a.d;
    qDebug()<<rsa_a.n;
    qDebug()<<rsa_b.e;
    qDebug()<<rsa_b.n;
    int i;
    //MD5
     QString  md5rslt=QCryptographicHash::hash(msg2.toLatin1(),QCryptographicHash::Md5).toHex();
     qDebug()<<"MD5:"<<md5rslt;
     //RSA签名，使用私钥签名
     QString rsaplaintext=md5rslt;        //hash值作为RSA明文测试，RSA单次加密最大1024字节
     QByteArray ba=rsaplaintext.toUtf8();   //QString 转字符数组
     char *plain=ba.data();
     int l=rsaplaintext.length();
     for(i=0;i<l;i++){
         rsa_a.plaintext[i]=plain[i];
     }
     rsa_a.Initialize();
     rsa_a.RSA_Signature();
     qDebug()<<"\n 签名完成 \n";
     QByteArray bs;
     for(i=0;i<l;i++){
         bs.append(intTo4ByteArray(rsa_a.Ciphertext[i]));
     }
     QString signature=bs.toBase64();//先转为base64编码再转化为字符串
     qDebug()<<"bs length"<<bs.length();
     qDebug()<<"signature"<<signature;
     qDebug()<<"signature length"<<signature.length();
     //AES加密，包含填充，QString->QByteArray
     QString key1=md5rslt.mid(0,32); //QString 转字符数组,确定AES密钥，以hash值作为初始密钥
     qDebug()<<key1;
     unsigned char* key;
     key=(unsigned char*)qstrdup(key1.toLocal8Bit().data());

     AES aes(key);//一次只能处理16字节数据，需要填充
     QString plaintext=msg+signature;
     qDebug()<<"the length of plaintext for AES "<<plaintext.length();
     l=plaintext.length();
     //先给输入字符串
     aes.input=plaintext;
     aes.aes_encrypt();//input->output2,得到的密文是output2，一个QByteArray数组
     qDebug()<<"AES密文的长度"<<aes.output.length();
    //将AES密钥进行RSA加密
     rsaplaintext=key1;
     ba=rsaplaintext.toUtf8();//QString 转字符数组
     char *plain2=ba.data();
     l=rsaplaintext.length();
     for(i=0;i<l;i++){
         rsa_b.plaintext[i]=plain2[i];
     }
     rsa_b.Initialize();
     rsa_b.RSA_Encrypt();//加密后的RSA密钥
     QByteArray aeskey;
     for(i=0;i<l;i++){
         aeskey.append(intTo4ByteArray(rsa_b.Ciphertext[i]));
     }
     qDebug()<<"rsa aes key length "<<aeskey.length();
    QByteArray rslt;
    rslt=aes.output2+aeskey;
    QString tmp;
    tmp=username+"-"+QString::number(msg.length())+"-"+QString::number(aes.aes_pading)+"-";
    qDebug()<<"tmp :"<<tmp;
    int length;
    length=tmp.toUtf8().length();
    qDebug()<<"tmp length"<<length;
    rslt=tmp.toUtf8()+rslt;
    qDebug()<<"rslt length"<<rslt.length();
    tcpClient->write(rslt.toBase64());
    qDebug()<<"have send";

    QMessageBox::information(0,"infor","伪造消息发送成功");
}*/
